<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<script>

  (function() {

    // until ES6 modules become standard, we follow Occam and simply stake out
    // a global namespace

    // Polymer is a Function, but of course this is also an Object, so we
    // hang various other objects off of Polymer.*

    var userPolymer = window.Polymer;

    window.Polymer = function(prototype) {
      // if input is a `class` (aka a function with a prototype), use the prototype
      // remember that the `constructor` will never be called
      if (typeof prototype === 'function') {
        prototype = prototype.prototype;
      }
      // if there is no prototype, use a default empty object
      if (!prototype) {
        prototype = {};
      }
      // desugar the prototype and return a factory object
      // Polymer.Base is now chained to prototype, and for IE10 compat
      // this may have resulted in a new prototype being created
      prototype = desugar(prototype);
      // we have a custom constructor if the constructor's prototype
      // is the prototype we're registering...
      var customCtor = prototype === prototype.constructor.prototype ?
        prototype.constructor : null;
      var options = {
        prototype: prototype
      };
      // NOTE: we're specifically supporting older Chrome versions here
      // (specifically Chrome 39) that throw when options.extends is undefined.
      if (prototype.extends) {
        options.extends = prototype.extends;
      }
      Polymer.telemetry._registrate(prototype);
      var ctor = document.registerElement(prototype.is, options);
      return customCtor || ctor;
    };

    var desugar = function(prototype) {
      // Note: need to chain user prototype with the correct type-extended
      // version of Polymer.Base; this is especially important when you can't
      // prototype swizzle (e.g. IE10), since CustomElements uses getPrototypeOf
      var base = Polymer.Base;
      if (prototype.extends) {
        base = Polymer.Base._getExtendedPrototype(prototype.extends);
      }
      prototype = Polymer.Base.chainObject(prototype, base);
      prototype.registerCallback();
      return prototype;
    };

    if (userPolymer) {
      for (var i in userPolymer) {
        Polymer[i] = userPolymer[i];
      }
    }

    Polymer.Class = function(prototype) {
      /*
      factoryImpl is required for a class constructor to be returned
      Because users of Polymer.Class always expect a class constructor,
      always provide a factoryImpl function
      */
      if (!prototype.factoryImpl) {
        prototype.factoryImpl = function() {};
      }
      return desugar(prototype).constructor;
    }

  })();

  /*
  // Raw usage
  [ctor =] Polymer.Class(prototype);
  document.registerElement(name, ctor);

  // Simplified usage
  [ctor = ] Polymer(prototype);
  */

  // telemetry: statistics, logging, and debug

  Polymer.telemetry = {
    registrations: [],
    _regLog: function(prototype) {
      console.log('[' + prototype.is + ']: registered')
    },
    _registrate: function(prototype) {
      this.registrations.push(prototype);
      Polymer.log && this._regLog(prototype);
    },
    dumpRegistrations: function() {
      this.registrations.forEach(this._regLog);
    }
  };

</script>
